package cn.dengta.webapp.trade.entity;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;

import cn.dengta.common.context.I18N;
import cn.dengta.common.model.BizFlag;
import cn.dengta.common.model.Messager;
import cn.dengta.context.model.TradeI18nKey;
import cn.dengta.webapp.base.entity.TimeBasedEntity;
import cn.dengta.webapp.trade.config.IntegralTradeProperties;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import me.codeplayer.util.CollectionUtil;

import static cn.dengta.webapp.trade.model.TradeTypeCore.calc;

/**
 * 用户积分账户
 */
@Setter
@Getter
@Accessors(chain = true)
@TableName("tr_user_integral")
public class UserIntegral extends TimeBasedEntity implements BizFlag.WritableBizFlag {

	/** 已提现过 */
	public static final long BIZ_FLAG_CASHED = 1L;

	/** 用户ID（=主键ID） */
	private Long userId;
	/** 资金总额 */
	protected BigDecimal totalAmount;
	/** 可用余额 */
	protected BigDecimal activeAmount;
	/** 冻结金额 */
	protected BigDecimal frozenAmount;
	/** 总积分 */
	protected BigDecimal totalIntegral;

	/** 旧版积分总额（含可用+冻结） */
	protected BigDecimal oldTotalAmount;

	/** 基于位运算的业务标识 */
	protected long bizFlag;

	public UserIntegral init(Long userId, Date now) {
		this.id = userId;
		this.userId = userId;
		this.totalAmount = frozenAmount = activeAmount = oldTotalAmount = totalIntegral = BigDecimal.ZERO;
		super.initTime(now);
		return this;
	}

	public BigDecimal opTotalAmount(char operator, BigDecimal amount) {
		return totalAmount = calc(totalAmount, operator, amount);
	}

	public BigDecimal opActiveAmount(char operator, BigDecimal amount) {
		return activeAmount = calc(activeAmount, operator, amount);
	}

	public BigDecimal opFrozenAmount(char operator, BigDecimal amount) {
		return frozenAmount = calc(frozenAmount, operator, amount);
	}

	public boolean hasNoEnough(BigDecimal amount) {
		return activeAmount.compareTo(amount) < 0;
	}

	public void setBizFlag(long bizFlag) {
		this.bizFlag = bizFlag;
	}

	/** 是否已提现过 */
	public boolean hasCashed() {
		return hasFlag(BIZ_FLAG_CASHED);
	}

	/**
	 * 积分转货币（同时自动扣减旧版总积分额度）
	 */
	public BigDecimal calcCashRMB(BigDecimal cashIntegral, IntegralTradeProperties config) {
		if (oldTotalAmount.compareTo(BigDecimal.ZERO) > 0) {
			final BigDecimal withOld = oldTotalAmount.min(cashIntegral); // 按照 15积分=1RMB 积分
			final BigDecimal withNew = cashIntegral.subtract(withOld); // 按照 10积分=1RMB 积分
			oldTotalAmount = oldTotalAmount.subtract(withOld);
			return config.calcIntegralToRMB(withOld, BigDecimal.valueOf(15))
					.add(config.calcIntegralToRMB(withNew));
		} else {
			return config.calcIntegralToRMB(cashIntegral);
		}
	}

	public <T> Messager<T> responseForNoBalance() {
		return Messager.status("less_integral", I18N.msg(TradeI18nKey.CASH_APPLY_INTEGRAL_NOT_ENOUGH));
	}

	public static Map<String, Object> asEmbed(UserIntegral source) {
		return asEmbed(source, t -> CollectionUtil.ofHashMap(
				"id", t.getId(),
				"activeAmount", t.getActiveAmount()
		));
	}

	public static Map<String, Object> asEmbedInfo(UserIntegral source) {
		return asEmbed(source, t -> CollectionUtil.ofHashMap(
				"id", t.getId(),
				"totalAmount", t.getTotalAmount(),
				"activeAmount", t.getActiveAmount(),
				"frozenAmount", t.getFrozenAmount()
		));
	}

	public static Map<String, Object> asEmbedInfoDesc(UserIntegral source) {
		return asEmbed(source, t -> CollectionUtil.ofHashMap(
				"id", t.getId(),
				"totalAmount", t.getTotalAmount().toPlainString(),
				"activeAmount", t.getActiveAmount().toPlainString(),
				"frozenAmount", t.getFrozenAmount().toPlainString()
		));
	}

	public static final String USER_ID = "user_id";
	public static final String TOTAL_AMOUNT = "total_amount";
	public static final String ACTIVE_AMOUNT = "active_amount";
	public static final String FROZEN_AMOUNT = "frozen_amount";

}
